package com.mvc.portal.web;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.mvc.base.model.BaseGroup;
import com.mvc.base.model.Supplier;
import com.mvc.base.service.SupplierManager;
import com.mvc.framework.FrameworkConstants;
import com.mvc.framework.config.ProjectConfig;
import com.mvc.framework.util.CookieUtils;
import com.mvc.framework.util.IpUtils;
import com.mvc.framework.util.MessageUtils;
import com.mvc.framework.web.FrameworkFilter;
import com.mvc.portal.model.LoginError;
import com.mvc.portal.model.OnlineUser;
import com.mvc.portal.model.Theme;
import com.mvc.portal.service.LoginErrorManager;
import com.mvc.portal.service.LoginManager;
import com.mvc.portal.service.OnlineUserManager;
import com.mvc.portal.service.ThemeManager;
import com.mvc.security.SecurityConstants;
import com.mvc.security.model.LoginLog;
import com.mvc.security.model.LoginResult;
import com.mvc.security.model.User;
import com.mvc.security.service.PasswordChangedManager;
import com.mvc.security.service.UserManager;
import com.mvc.security.util.SecurityUtils;

@Controller
@RequestMapping("/login")
public class LoginController {
	private static final Logger	   LOGGER	= Logger.getLogger(LoginController.class);
	@Autowired
	private UserManager	           userManager;
	@Autowired
	private LoginManager	       loginManager;
	@Autowired
	private ThemeManager	       themeManager;
	@Autowired
	private OnlineUserManager	   onlineUserManager;
	@Autowired
	private LoginErrorManager	   loginErrorManager;

	@Autowired
	private SupplierManager	       supplierManager;

	@Autowired
	private PasswordChangedManager	passwordChangedManager;

	@RequestMapping(value = "")
	public String index(HttpServletRequest request, HttpServletResponse response, User user) {
		String message = "";
		if (null != request.getSession().getAttribute(SecurityConstants.SECURITY_TOKEN)) {
			return "redirect:/index";
		}
		if (null != user) {
			if (null != user.getLoginName()) {
				String randomCode = request.getParameter(SecurityConstants.RANDOM_CODE);
				if (null == randomCode || !randomCode.equals((String) request.getSession().getAttribute(SecurityConstants.RANDOM_CODE))) {
					message = "验证码错误";
				} else {
					LoginLog loginLog = loginManager.beginLog(user);
					loginLog.setIp(IpUtils.getRealIp(request));
					boolean bool = checkUserLoginError(request, user);
					if (bool) {
						boolean pass = userManager.authentication(user);
						if (pass) {
							User temp = userManager.getUserByLoginName(user.getLoginName());
							if (temp.getSex() != null && temp.getSex() == BaseGroup.STATUS_INVALID) {
								message = "帐号已被锁定，不能登录";
							} else {
								if (passwordChangedManager.isNeedChangePassword(temp.getObjectId())) {
									request.getSession().setAttribute(SecurityConstants.USER_ID, temp.getObjectId());
									request.getSession().setAttribute(SecurityConstants.LOGIN_NAME, temp.getLoginName());
									return "redirect:/user/changePassword";
								} else {
									loginSuccess(request, response, user, loginLog);
									saveOnlineUser(request, temp, loginLog);
									return "redirect:/index";
								}
							}
						} else {
							if (StringUtils.isBlank(message)) {
								message = "用户名或密码错误.";
							}
						}
						loginLog.setResult(LoginLog.LOGIN_RESULT_FAIL);
						request.setAttribute(FrameworkConstants.MESSAGE, message);
						saveLoginError(request, user);
					} else {
						loginLog.setResult(LoginLog.LOGIN_RESULT_FAIL);
						message = MessageUtils.getMessage(LoginResult.LOGIN_LOCKED.message, request);
						saveLoginError(request, user);
					}
					loginLog.setMessage(message);
					loginManager.createLog(loginLog);
				}
			}
		} else {
			message = request.getParameter("message");
		}
		String skin = CookieUtils.getCookieByName(request.getCookies(), FrameworkConstants.SKIN);
		if (StringUtils.isBlank(skin)) {
			skin = ProjectConfig.getDefaultSkin();
		}
		request.getSession().setAttribute(FrameworkConstants.SKIN, skin);
		request.setAttribute("message", message);
		return "portal/login";
	}

	private void saveOnlineUser(HttpServletRequest request, User user, LoginLog loginLog) {
		if (loginLog.getResult() == LoginLog.LOGIN_RESULT_SUCCESS) {
			OnlineUser onlineUser = onlineUserManager.getOnlineByUserId(user.getObjectId(), null);
			if (onlineUser != null) {
				onlineUser.setStatus(OnlineUser.STATUS_OFFLINE);
				onlineUserManager.save(onlineUser);
			}
			OnlineUser currentOnlineUser = new OnlineUser();
			currentOnlineUser.setBeginDate(loginLog.getBeginDate());
			currentOnlineUser.setUserId(user.getObjectId());
			currentOnlineUser.setUserName(user.getUserName());
			currentOnlineUser.setSessionId(request.getSession().getId());
			currentOnlineUser.setStatus(OnlineUser.STATUS_ONLINE);
			onlineUserManager.save(currentOnlineUser);
		}
	}

	private void loginSuccess(HttpServletRequest request, HttpServletResponse response, User user, LoginLog loginLog) {
		loginLog.setResult(LoginLog.LOGIN_RESULT_SUCCESS);
		HttpSession session = request.getSession();
		String token = SecurityUtils.generateSecurityToken(user.getLoginName());
		user = userManager.getUserByLoginName(user.getLoginName());
		session.setAttribute("userDepartmentName", "ALL");

		loginLog.setUserId(user.getObjectId());
		// 如果登录成功 清楚登录错误日志
		loginErrorManager.deleteByWhere(" local_Ip = '" + loginLog.getIp() + "' AND login_Name = '" + user.getLoginName() + "'");

		Theme theme = themeManager.getThemeByUserId(user.getObjectId());
		String skin = ProjectConfig.getDefaultSkin();
		if (null != theme) {
			skin = theme.getSkin();
		}
		CookieUtils.setCookie(response, FrameworkConstants.SKIN, skin);
		CookieUtils.setUserTokenCookie(response, token);
		CookieUtils.setEncodedCookie(response, SecurityConstants.LOGIN_NAME, user.getLoginName());
		session.setAttribute(SecurityConstants.SECURITY_TOKEN, token);
		FrameworkFilter.setUserToSession(request, response, token, skin);
		session.setAttribute(SecurityConstants.SESSION_USER, user);
		session.setAttribute(SecurityConstants.LOGIN_NAME, user.getLoginName());
		session.setAttribute(SecurityConstants.FULL_NAME, user.getUserName());
		session.setAttribute(SecurityConstants.USER_ID, user.getObjectId());
		session.setAttribute(SecurityConstants.SESSION_USER, user);
		if (user.getType() != null && user.getType() == ExtendUserController.USER_SUPPLIER) {
			Supplier supplier = supplierManager.getSupplierByLoginUserId(user.getObjectId());
			if (supplier != null) {
				session.setAttribute("supplierId", supplier.getObjectId());
			}
		}
		loginManager.createLog(loginLog);
	}

	private void saveLoginError(HttpServletRequest request, User user) {
		LoginError loginError = new LoginError();
		loginError.setLocalIp(IpUtils.getRealIp(request));
		loginError.setLoginName(user.getLoginName());
		loginError.setLoginDate(new Date());
		loginErrorManager.save(loginError);
	}

	private boolean checkUserLoginError(HttpServletRequest request, User user) {
		Boolean bool = false;
		int count = loginErrorManager.getSuccessionLoginErrorCount(user.getLoginName(), IpUtils.getRealIp(request));
		if (count >= 3) {
			/**
			 * 超过30分钟 返回True 《此处可控制是此IP地址不能登录本系统，还是此IP的不能用此用户再次登录》
			 */
			bool = loginErrorManager.isOutOfRestrictTime(user.getLoginName(), IpUtils.getRealIp(request));
			if (bool) {
				loginErrorManager.deleteByWhere(" local_Ip = '" + IpUtils.getRealIp(request) + "' AND login_Name = '" + user.getLoginName()
				        + "'");
			}
		} else {
			bool = true;
		}
		return bool;
	}

	@RequestMapping(value = "out")
	public String loginOut(HttpServletRequest request) {
		Integer userId = (Integer) request.getSession().getAttribute(SecurityConstants.USER_ID);
		String logoutFrom = request.getParameter("logoutFrom");
		onlineUserManager.deleteOnlineUser(userId, Integer.parseInt(logoutFrom));
		request.getSession().invalidate();
		return "redirect:/index";
	}

}
